
/// <reference path="./../utils/EventDispatcher.ts" />
/// <reference path="./../utils/Maps.ts" />
/// <reference path="./BaseModule.ts" />
/// <reference path="./../storage/BaseStorage.ts" />
/// <reference path="./../storage/StorageMgr.ts" />

namespace apeng {


	/**数据管理 避免数据模块之间循环引用 */
	export class ModuleMgr<TType> extends EventDispatcher {

		public readonly EventType = {
			/**实例化完成 */
			INSTANCE: "INSTANCE",
			/**启动队列 */
			START_UP: "START_UP",
			/**run完成 */
			RUN_COMLETE: "RUN_COMLETE",
		}

		private modules: { [moduleType: number]: BaseModule } = {}

		public modelTypeOrgin: any = null!

		public _adds: TModuleType = {}
		public add(type: TType) {
			let _this = this
			return function (target: new () => BaseModule) {
				_this._adds[type as any] = target
			}
		}

		/**获取实例化后的模块 */
		public get<T extends BaseModule>(moduleType: number): T {
			return this.modules[moduleType] as T
		}

		public instanceOnce(moduleType: number) {
			let module = this._adds[moduleType]
			let value = this.modules[moduleType as any] = new module()
			value.storage = new BaseInstanceStorage(CStorageDefaultType, StorageMgr)
			if (value.onBeforeInstance)
				value.onBeforeInstance()
			if (value.onInstance)
				value.onInstance()

			return value
			this.emit(this.EventType.INSTANCE)
		}


		/**实例化时 */
		public instance(useCacheType: boolean) {
			let modules = this._adds
			console.log("module count:" + Maps.size(modules))
			Maps.forEach(modules, (module, moduleName) => {
				let value = this.modules[moduleName as any] = new module()
				value.storage = new BaseInstanceStorage(useCacheType ? Number(moduleName) : CStorageDefaultType, StorageMgr)
				if (value.onBeforeInstance)
					value.onBeforeInstance()
			})
			Maps.forEach(this.modules, module => {
				if (module.onInstance)
					module.onInstance()
			})
			this.emit(this.EventType.INSTANCE)
		}

		public forEach(cb: (module: BaseModule) => void) {
			Maps.forEach(this.modules, cb)
		}

		public run(complete: () => void, _enum?: any) {
			console.log("module START_UP start")
			this.emitQueue(this.EventType.START_UP, -1, () => {
				console.log("module START_UP complete")
				Maps.forEach(this.modules, module => {
					if (module.onCreate)
						module.onCreate()
				})
				Maps.forEach(this.modules, module => {
					if (module.onLogic)
						module.onLogic()
				})
				Maps.forEach(this.modules, module => {
					if (module.onComplete)
						module.onComplete()
				})
				complete()

				this.emit(this.EventType.RUN_COMLETE)
			}, _enum ? ((index) => "START_UP " + _enum[index]) : "START_UP")
		}


	}
}